<script setup>
import { computed, ref,watch,h } from 'vue'

import { Handle, Position, useVueFlow } from '@vue-flow/core'
import { VMarkdownView } from 'vue3-markdown'
import { NImage, NImageGroup, NSpace, NText, useMessage } from 'naive-ui';
import { createLyla } from '@lylajs/web'
import { NodeHandler } from './node.js'
import BaseNode from './BaseNode.vue';
import Net from './net.js'


// const TEST_SERVER = import.meta.env.VITE_SERVER

const { lyla } = createLyla({ context: null })

const { updateNodeData, getConnectedEdges, onConnect, getNodes } = useVueFlow()
const message = useMessage()
const props = defineProps(['id', 'data','toggle','sourceData'])
const data = ref({
  searched: false
})
updateNodeData(props.id, {data:"Ok",sourceData:"sss"})
const targetId = ref("");

onConnect((params) => {
  console.log('target to:', params)
  if (params.target != null) {
    targetId.value = params.source
  }
})

const results = ref('')
const loading =ref(false)
const showDetail = ref(false)
const showNetResult = ref(false)
const tableData = ref([])


const netTemplate = ref({
  name: "",
  type: "curl",
  api:"",
  headers: {
    "Content-Type": "application/json",
    "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/98.0.4758.102 Safari/537.3"    
  },
  cookie: "",
  usepost: true,
  stream: true,
  inputArgs: [],
  outputArgs: [],
  data: {},
})
const tableColumns = computed(() => {
  if (tableData.value == null){
    return [];
  }
  let keys = Object.keys(tableData.value[0])
  let ds = []
  for(let k of keys){
    
    ds.push({
      title: k,
      key: k.toLowerCase(),
      sorter: (row1, row2) =>  {
        if (typeof row1[k] == "number" ){
          return row1[k] - row2[k]
        }else if (typeof row1[k] == "string"){
          return  row1[k].localeCompare(row2[k])
        }else{
          return 0
        }    
      },
      render(row){
        // re match markdown link
        let text = row[k];
        if (typeof text == "string" && text.match(/\[(.*?)\]\((.*?)\)/)){
          // use VMarkdownView to render markdown text
          // remove ![xxx](data:image/png;base64,..)
          text = text.replace(/\!\[(.*?)\]\((.*?)\)/g, "");
          // remove ![xxx](data:image/png;base64,..)
          return h(VMarkdownView, {
            content: text,
            mode:"dark",
            style:"border-radius: 8px;border: 1px solid gray;margin: 0px;padding: 13px;overflow: auto;"
          }, null)
        }else if (Array.isArray(text)){
          let array = [];
          let imgs = [];
          for (let tex of text){
            if (typeof tex == "string" && tex.match(/data\:image\/png\;base64\,/)){
              let imageDatas = tex.split("data:image/png;base64,");
              
              for (let img of imageDatas){
                if (img.indexOf(")")> 0){
                  let imgData = img.split(")")[0]
                  imgs.push(h(NImage, {
                    src: "data:image/png;base64," + imgData,
                    width: 100,
                  }))
                }
              }
            }else{
              array.push(tex)
            }
          }
          if (imgs.length > 0){
            array.push(h(
              NImageGroup,{},
              h(NSpace,{
                vertical: true,
                },...imgs)
            ))
          }
          return h(NSpace, {}, ...array)
        }else{
          if (typeof text == "string" && text.match(/data\:image\/png\;base64\,/)){
            let imageDatas = text.split("base64,");
            let imgs = [];
            for (let img of imageDatas){
              if (img.indexOf(")")> 0){
                let imgData = img.split(")")[0]
                imgs.push(h(NImage, {src: "data:image/png;base64," + imgData}))
              }
            }
            return h(NSpace, {}, ...imgs)
          }else{
            return text
          }
          
        }
        
      }
    })
  }
  
  return ds
})
const SEARCH_API  =  ref('')
const inputValue = ref('');
const netTypes = ref([{
  label: 'search',
  value: 'curl',
}])

const postValue = ref([])
const headerValue = ref([])
const requestArgs = ref({})


setTimeout(()=>{
  updateNodeData(props.id, {toggle: false})
  watch(()=>props.data.toggle, (nv, ov)=>{
      if (props.data.toggle == true){
        props.data.toggle = false
        message.success("开始网络请求");
        toggle()
      }
  },{ deep: true })
},300)



const toggle = () =>{
  loading.value = true
  showDetail.value = false
  results.value = ''
  let items = [];
  let columns = [];
  let isTable = false;
  let node = new NodeHandler(netTemplate.value.name, netTemplate.value.type)
  console.log("req:",requestArgs.value)
  node.from_net_template(netTemplate).stream(requestArgs.value, (each_data)=>{
    console.log("each_data:",each_data)
    results.value += "\n"+  JSON.stringify(each_data, null, 2)
    for(let item of each_data){
      items.push(item);
      let keys = Object.keys(item);
      if (columns.length == 0){
        for(let key of keys){
          columns.push(key);
        }
      }else{
        if (columns.length == keys.length){
          isTable = true;
        }
      }
    }
    if (isTable){
      // showNetResult.value = true;
      if (tableData.value == null){
        tableData.value = [];
      }
      for(let item of each_data){
        tableData.value.push(item);
      }
    }
  },()=>{
    loading.value = false
    
  },(err)=>{
    message.error(err)
  })
}

const load_nodes = ref([])
const use_node_name = ref("");

watch(use_node_name, (newValue, oldValue) => {
  console.log(`use_node_name changed from ${oldValue} to ${newValue}`)
  loadNetSearch()
})

const saveNetSearch = ()=>{
  if (netTemplate.value.name == "" || netTemplate.value.api == ""){
    message.error("请输入节点名称和api")
    return
  }
  let node = new NodeHandler(netTemplate.value.name, netTemplate.value.type)
  // node.server = TEST_SERVER;
  node.from_net_template(netTemplate).save(()=>{
    message.success("保存成功")
  })
}

const loadNetSearch = ()=>{
  let node = new NodeHandler(use_node_name.value)
  // node.server = TEST_SERVER;
  node.load((data)=>{
    console.log("load node: ",data)
    netTemplate.value.data = data.data
    netTemplate.value.cookie  = data.cookie
    netTemplate.value.headers = data.headers
    netTemplate.value.api = data.api
    netTemplate.value.name = data.name
    netTemplate.value.type = data.type
    netTemplate.value.inputArgs = data.args
    netTemplate.value.outputArgs = data.outputArgs
    netTemplate.value.stream = data.stream
    netTemplate.value.usepost = data.usepost
    for (let k of data.args){
      requestArgs.value[k] = ""
    }
    headerValue.value = [];
    postValue.value = [];
    for (let key in data.headers){
      headerValue.value.push({
        key: key,
        default: data.headers[key]
      })
    }
    for(let key in data.data){
      
      let val = data.data[key]
      let tp = "text"
      if (typeof val == "number"){
        tp = "number"
      }else if (typeof val == "boolean"){
        tp = "boolean"
      }else if (typeof val == "string"){
        tp = "text"
      }

      postValue.value.push({
        key: key,
        default: val,
        type: tp,
      })
    }
  })
}

const list_net_node = ()=>{
  NodeHandler.List((data)=>{
    for(let k of data){
      // console.log(`node: `,k)
      if ( k.type != null && !k.type.endsWith("Agent") ){
        load_nodes.value.push(k)
      }
    }
  })
  // },TEST_SERVER)
}

setTimeout(()=>{
  list_net_node()
}, 300)

const newTypes = ref([{
  label: "string",
  value: "text",
},{
  label: "number",
  value: "number",
},{
  label: "boolean",
  value: "boolean",
}])

const onCreate = ()=>{
  return {
    key: "",
    default: null,
    type: "text",
  }
}

watch(()=> postValue, ()=>{
  let target = {}
  
  for(let arg of postValue.value){
    // console.log(`arg: `,arg)
    let key = arg.key;
    target[key] = arg.default
  }
  netTemplate.value.data = target
  
}, {deep: true})


watch(()=> headerValue, ()=>{
  let target = {}
  
  for(let arg of headerValue.value){
    // console.log(`arg: `,arg)
    let key = arg.key;
    target[key] = arg.default
  }
  netTemplate.value.headers = target
  
}, {deep: true})

const args = computed(()=>{
  return netTemplate.value.inputArgs.map((name) => {
    return `$\{${name}\}`
  })
})

const downResult = ()=>{
  fetch("/down_results",{
    method:"post",
    headers:{
      "Content-Type":"application/json"
    },
    body:JSON.stringify({
      data:tableData.value
    })
  }).then(d => d.json()).then(d=>{
    let url = d.url
    let tmpA = document.createElement("a")
    tmpA.download = d.name
    tmpA.href = url
    document.body.appendChild(tmpA);
    tmpA.click()
    document.body.removeChild(tmpA);
    // tmpA.remove();
  })
}

</script>


<template>
  <BaseNode :loading="loading" v-model:value="tableData" target :id="props.id" >
      <!-- <div style="min-width: 200px; max-height: 500px; overflow-y: auto"> -->
        
          <n-space  vertical >
            <n-select :options="load_nodes" v-model:value="use_node_name"  placeholder="加载网络节点配置"  ></n-select>
            <!-- <n-input v-if="netTemplate.api != ''"  @keyup.enter="search" v-model:value="inputValue"  placeholder="搜索内容"  /> -->
          </n-space>
          <n-list>
            <n-list-item v-if="netTemplate.inputArgs.length > 0" >
                <n-space justify="space-between" vertical >
                    <n-input v-for="arg in netTemplate.inputArgs" v-model:value="requestArgs[arg]" :placeholder="arg" @keyup.enter="toggle" />
                </n-space>
            </n-list-item>
            <n-list-item>
              <n-space    vertical style="margin-top: 10px;"   >
                <n-flex>
                  <n-button @click="showDetail = true"> 详细配置</n-button>
                  <n-button @click="showNetResult = true"> 显示结果:{{ tableData.length }}</n-button>
                  <n-button @click="downResult" v-if="tableData.length > 0" > 下载结果:{{ tableData.length }}</n-button>
                  <n-button type="success" v-if="netTemplate.api != ''"  @click="toggle">搜索</n-button>
                </n-flex>
                
              </n-space>
            </n-list-item>
            
          </n-list>
        
      <!-- </div> -->
      <n-drawer v-model:show="showDetail" width="600"  placement="right">
        <n-drawer-content>
          <n-list>
            <n-list-item>
              <n-gradient-text type="info" :size="20" >加载网络节点配置:</n-gradient-text>
              
              <n-select :options="load_nodes" v-model:value="use_node_name"  placeholder="加载网络节点配置"  ></n-select>
            </n-list-item>
            
            <n-list-item>
              <n-gradient-text type="success" :size="20">添加变量：</n-gradient-text>
                <n-dynamic-tags v-model:value="netTemplate.inputArgs" />
                
            </n-list-item>
            <n-list-item v-if="netTemplate.type == 'curl'">
              <n-gradient-text type="info" :size="20" >配置请求</n-gradient-text>

              <n-space  vertical >
                
                <n-input v-model:value="netTemplate.name"  placeholder="节点保存名称"  />
                
                <n-flex justify="space-between">
                  <n-flex>
                    <n-text type="info" >流式传输：</n-text>
                    <n-switch v-model:value="netTemplate.stream"  placeholder="流式传输"  />
                  
                  </n-flex>
                  <n-flex>
                    <n-text type="info" >POST/GET</n-text>
                    <n-switch v-model:value="netTemplate.usepost"  placeholder="POST/GET"  >
                      <template #checked>使用POST</template>
                      <template #unchecked>使用GET</template>
                    </n-switch>
                  </n-flex>
                  
                </n-flex>
                
                <n-flex justify="space-between">
                  <n-text type="info" >API 地址：</n-text>
                  <n-input v-model:value="netTemplate.api"  placeholder="API 地址"  />
                </n-flex>
                
                <n-text type="warning">设置Cookie:</n-text> 
                <n-input type="textarea" row="5" v-model:value="netTemplate.cookie"  placeholder="设置Cookie"  />
                <n-text type="warning" >设置请求头：</n-text>
                <n-dynamic-input v-model:value="headerValue" :on-create="onCreate" >
                  <template #create-button-default>
                    增加请求数据参数
                  </template>
                  <template #default="{ value }">
                  <div style="display: flex; align-items: center; width: 100%">
                    <n-input v-model:value="value.key" type="text" style="margin-right: 3px; max-width: 150px" />
                    <n-input v-model:value="value.default" type="text" />
                    
                    
                  </div>
                </template>
                </n-dynamic-input>
                <n-text type="info">POST请求参数：</n-text>
                <n-dynamic-input v-model:value="postValue" :on-create="onCreate" >
                <template #create-button-default>
                  增加请求数据参数
                </template>
                <template #default="{ value }">
                  <div style="display: flex; align-items: center; width: 100%">
                    <n-select v-model:value="value.type" :options="newTypes" style="margin-right: 3px; max-width: 100px"   placement="设置默认参数类型"  ></n-select>
                    <n-input v-model:value="value.key" type="text" style="margin-right: 3px; max-width: 70px" />

                    <!-- <n-input v-if="value.type == 'text'"  v-model:value="value.default" type="text" /> -->
                    <n-auto-complete
                      v-if="value.type == 'text'"
                      v-model:value="value.default"
                      :input-props="{
                        autocomplete: 'disabled',
                      }"
                      :options="args"
                      placeholder="参数"
                      clearable
                    />
                    <n-input-number v-else-if="value.type == 'number'"  v-model:value="value.default" type="text" />
                    <n-checkbox v-else-if="value.type == 'boolean'" v-model:checked="value.default" />
                  </div>
                </template>
              </n-dynamic-input>
              
              <pre>{{ JSON.stringify(netTemplate.data, null, 2) }}</pre>
              </n-space>
            </n-list-item>

            <n-list-item>
              <n-text type="info" >结果如何选取： </n-text>
                <pre>
exmple: {
  "items": [{...},{...}],
  "key2": {
    "out1": [...out1 list ...],
    "out2": [...out2 list ...],
  }
}
结果选择： <n-text type="success">"itmes": </n-text>
会输出： [{...},{...}],
结果选择： <n-text type="success">"key2" , "out1":</n-text>
会输出： [...out1 list ...]
                </pre>
                <n-dynamic-tags v-model:value="netTemplate.outputArgs" />
            </n-list-item>
            <n-list-item>
              <n-button style="width: 100%;" strong size="large"  @click="saveNetSearch">保存</n-button>
            </n-list-item>
          </n-list>

          <n-code :code="results" language="json" show-line-numbers >
            <!-- {{results}} -->
          </n-code>
          
          
        </n-drawer-content>
      </n-drawer>

    <n-drawer v-model:show="showNetResult" :width="1200" placement="left">
      <n-drawer-content>
          <n-flex><n-button @click="showNetResult = false">X</n-button></n-flex>
          <n-data-table  v-if="tableData != null" :data="tableData" :columns="tableColumns">
          </n-data-table>
      </n-drawer-content>
      
    </n-drawer>
  </BaseNode>
</template>